package sistema;

import java.io.Serializable;
import java.util.*;

import dados.Contato;
import dados.Evento;
/**
 * Uma agenda que guarda contatos e eventos
 */
public class Agenda implements Serializable{

	private static final long serialVersionUID = 1L;
	private List<Contato> contatos;
	private List<Evento> eventosFuturos, eventosPassados;
	/**
	 * Cria uma agenda
	 */
	public Agenda(){
		eventosFuturos = new ArrayList<Evento>();
		eventosPassados = new ArrayList<Evento>();
		contatos = new ArrayList<Contato>();
	}
	/**
	 * A Lista de contatos na agenda
	 * @return Um arraylist de contatos
	 */
	public List<Contato> getContatos(){
		return contatos;
	}
	/**
	 * Os eventos futuros na agenda
	 * @return Um arraylist de Evento
	 */
	public List<Evento> getEventosFuturos(){
		reorganizaEventos();
		return eventosFuturos;
	}
	/**
	 * retorna a lista de eventos passados
	 * @return um arraylist de evento
	 */
	public List<Evento> getEventosPassados(){
		reorganizaEventos();
		return eventosPassados;
	}
	/**
	 * Addiciona um novo evento a Agenda.
	 * @param evento O evento a ser Adicionado.
	 * @param sobrecarregar Se deve fazer sobrecarga de horario ou nao.
	 * @return Um objeto Evento se houve conflito de horario,null se o novo evento foi corretamente adicionado.
	 */
	@SuppressWarnings("static-access")
	public Evento addEvento(Evento evento,boolean sobrecarregar){
		if (!sobrecarregar){
			for(Evento e1: eventosPassados){
				if (evento.temConflitoDeHorario(e1)){
					return e1;
				}
			}
			for(Evento e2: eventosFuturos){
				if (evento.temConflitoDeHorario(e2)){
					return e2;
				}
			}
		}
		Calendar calendar = Calendar.getInstance();
		String horaAtual,diaAtual;
		horaAtual = String.format("%02d:%02d", calendar.get(calendar.HOUR_OF_DAY),calendar.get(calendar.MINUTE));
		diaAtual = String.format("%02d/%02d/%04d", calendar.get(calendar.DAY_OF_MONTH),
				calendar.get(calendar.MONTH)+1,calendar.get(calendar.YEAR));
		Evento esteMomento = null;
		try {
			esteMomento = new Evento("Este Momento",diaAtual,horaAtual,"00:00","Agora");
		} catch (Exception e) {}
		if (evento.compareTo(esteMomento) > 0){
			eventosFuturos.add(evento);
			reorganizaEventos();
			return null;
		}
		eventosPassados.add(evento);
		reorganizaEventos();
		return null;
	}
	/**
	 * Adiciona um evento sobrescrevendo todos os que derem conflito de horario com ele.
	 * @param evento O evento a ser adicionado
	 */
	@SuppressWarnings("static-access")
	public void sobrescreveEventosConflitantes(Evento evento){
		for(int i = eventosPassados.size()-1 ; i >= 0; i--){
			if (evento.temConflitoDeHorario(eventosPassados.get(i))){
				eventosPassados.remove(i);
			}
		}
		for(int i = eventosFuturos.size()-1 ; i >= 0; i--){
			if (evento.temConflitoDeHorario(eventosFuturos.get(i))){
				eventosFuturos.remove(i);
			}
		}
		Calendar calendar = Calendar.getInstance();
		String horaAtual,diaAtual;
		horaAtual = String.format("%02d:%02d", calendar.get(calendar.HOUR_OF_DAY),calendar.get(calendar.MINUTE));
		diaAtual = String.format("%02d/%02d/%04d", calendar.get(calendar.DAY_OF_MONTH),
				calendar.get(calendar.MONTH)+1,calendar.get(calendar.YEAR));
		Evento esteMomento = null;
		try {
			esteMomento = new Evento("Este Momento",diaAtual,horaAtual,"00:00","Agora");
		} catch (Exception e) {}
		if (evento.compareTo(esteMomento) > 0){
			eventosFuturos.add(evento);
			reorganizaEventos();
			return;
		}
		eventosPassados.add(evento);
		reorganizaEventos();
		return;
	}
	/**
	 * Procura por um contato cujo nome comeca com a string dada
	 * @param nome Parte do nome, ou nome completo do contato
	 * @return Uma lista de contatos desejado
	 */
	public List<Contato> procuraContato(String nome){
		nome =nome.toLowerCase();
		String nome2;
		List<Contato> contatosEncontrados= new ArrayList<Contato>();
		for(Contato c: getContatos()){
			nome2 = c.getNome().toLowerCase();
			if(nome2.startsWith(nome)){
				contatosEncontrados.add(c);
			}
		}
		return contatosEncontrados;
	}
	/**
	 * Procura por eventos associados a um certo contato.
	 * @param c1 o Contato desejado.
	 * @return Uma Lista de Eventos associados a c1.
	 */
	public List<Evento> procuraEventoPorContato(Contato c1){
		List<Evento> eventos = new ArrayList<Evento>();
		for(Evento e1: eventosFuturos){
			if (e1.getContatosRelacionados().contains(c1)){
				eventos.add(e1);
			}
		}
		for(Evento e2: eventosPassados){
			if (e2.getContatosRelacionados().contains(c1)){
				eventos.add(e2);
			}
		}
		return eventos;
	}
	/**
	 * Remove um contato da lista de contatos
	 * @param contato Contato a ser removido
	 */
	public void removeContato(Contato contato){
		for(Contato c: getContatos()){
			if(c.equals(contato)){
				getContatos().remove(c);
				break;
			}
		}
	}

	/**
	 * Adiciona um novo contato ao Usuario, se for achado um com mesmo e-mail,
	 * o metodo olha se deve ser sobrescrito o contato antigo, caso nao, o contato nao sera adicionado.
	 * @param contato O contato a ser adicionado.
	 * @param sobrescrever Se o Usuario deseja Sobrescrever o Contato antigo ou nao.
	 * @return O sucesso ou nao da operacao
	 */
	public boolean addContato(Contato contato,boolean sobrescrever){
		if (!sobrescrever){
			if (getContatos().contains(contato)){
				return false;
			}
		}
		if(getContatos().contains(contato)){
			contatos.remove(contato);
		}
		contatos.add(contato);
		return true;
	}

	
	/**
	 * Uma String representando a lista de eventos do Usuario
	 * @return A lista de eventos em forma de String
	 */
	public String listaEventos(){
		reorganizaEventos();
		String eventosPassados="";
		String eventosFuturos ="";
		for(Evento e: getEventosFuturos()){
			eventosFuturos+= e.toString()+ "\n";
		}
		for(Evento e: getEventosPassados()){
			eventosPassados+=e.toString()+"\n";
		}
		return "Lista de Eventos Futuros: \n" +eventosFuturos + "\n" + "Lista de eventos Passados: \n"+eventosPassados;
	}

	
	@SuppressWarnings("static-access")
	/**
	 * Reorganiza os eventos, jogando um evento para eventos passados por exemplo
	 * e os organizandos por data e hora
	 */
	public void reorganizaEventos(){
		Calendar calendar = Calendar.getInstance();
		String horaAtual,diaAtual;
		horaAtual = String.format("%02d:%02d", calendar.get(calendar.HOUR_OF_DAY),calendar.get(calendar.MINUTE));
		diaAtual = String.format("%02d/%02d/%04d", calendar.get(calendar.DAY_OF_MONTH),
				calendar.get(calendar.MONTH) + 1,calendar.get(calendar.YEAR));
		Evento esteMomento = null;
		try {
			esteMomento = new Evento("Este Momento",diaAtual,horaAtual,"00:00","Agora");
		} catch (Exception e) {}

		for(int i = eventosFuturos.size() - 1; i >= 0; i--){
			if (eventosFuturos.get(i).compareTo(esteMomento) < 0){
				eventosPassados.add(eventosFuturos.get(i));
				eventosFuturos.remove(i);
			}
		}
		Collections.sort(eventosFuturos);
		Collections.sort(eventosPassados);
	}
	/**
	 * Retorna uma lista com os eventos cujo nome contem os caracteres passados como parametro.
	 * Nao e case sensitive.
	 * @param nome Nome para pesquisar pelo evento.
	 * @return Uma lista com os eventos cujo nome tem uma intersecao com o nome passado.
	 */
	public List<Evento> procuraEvento(String nome){
		//coloquei pra retornar uma lista de eventos de acordo com o nome passado pra ficar mais facil na hora da interface(eu acho)
		//mas mudem ae se achar melhor
		List<Evento> eventosSelecionados= new ArrayList<Evento>();
		for(Evento e: eventosFuturos){
			if(e.getNome().toLowerCase().contains(nome.toLowerCase())){
				eventosSelecionados.add(e);
			}
		}
		for(Evento e: eventosPassados){
			if(e.getNome().toLowerCase().contains(nome.toLowerCase())){
				eventosSelecionados.add(e);
			}
		}
		return eventosSelecionados;
	}
	/**
	 * Remove um evento da agenda.
	 * @param evento O objeto evento a ser removido.
	 */
	//pensei em, na interface, verfica com o metodo procuraEvento, e manda remover com esse.
	public void removeEvento(Evento evento){
		for(Evento e: eventosFuturos){
			if(e.equals(evento)){
				getEventosFuturos().remove(e);
				return;
			}
		}
		for(Evento e: eventosPassados){
			if(e.equals(evento)){
				getEventosPassados().remove(e);
				return;
			}
		}
	}

	

	/**
	 * Retorna a lista de Contatos associados ao evento.
	 * @param evento Evento a ser chegado.
	 * @return um List<Candidato>.
	 */
	public List<Contato> contatosDoEvento(Evento evento){
		return evento.getContatosRelacionados();
	}

}
